package com.suixuan.support.log;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

import org.apache.commons.lang.ArrayUtils;
import org.apache.log4j.LogManager;

/**
 * 
 * Nanjing Zhou Su co.,Ltd
 * 
 * @Title: LogFactoryThread.java
 * @Package: com.suixuan.log
 * @Description: 异步记录日志
 * @Author: suixuan
 * @Date Jul 16, 2010 4:10:51 PM
 * @Version V1.0
 * 
 */

public class LogFactoryThread implements Runnable {

	private static final int QUEUE_MAX_SIZE = 1024 * 10 * 4;

	/**
	 * 双端阻塞队列
	 */
	private static BlockingQueue<LogBean> joinPointQueue = new LinkedBlockingQueue<LogBean>(QUEUE_MAX_SIZE);

	private static ExecutorService executor = Executors.newScheduledThreadPool(1);

	private static final LogFactoryThread LOG_FACTORY_THREAD = new LogFactoryThread();

	public static final LogFactoryThread getInstance() {
		return LOG_FACTORY_THREAD;
	}

	/**
	 * 构造方法
	 */
	private LogFactoryThread() {
		super();
		// 启动线程
		executor.execute(this);
	}

	public void put(LogBean joinPoint) {
		// 队列到达最大值后，如继续有数据将抛弃
		if (joinPointQueue.size() < QUEUE_MAX_SIZE) {
			try {
				joinPointQueue.put(joinPoint);
			} catch (InterruptedException e) {
				LogFactory.getInstance(LogFactoryThread.class).logRecord(LogConstant.ERROR, e.toString(), e);
			}
		}
	}

	@Override
	public void run() {
		LogBean logBean = null;
		while (true) {
			try {
				logBean = joinPointQueue.take();
			} catch (InterruptedException e) {
				LogFactory.getInstance(LogFactoryThread.class).logRecord(LogConstant.ERROR, e.toString(), e);
				logBean = null;
			}

			// 记录日志
			if (null != logBean) {
				LogFactory.getInstance(logBean.getClazz())
						.logRecord(logBean.getLogConstant(), this.recordLogs(logBean));
			}
		}
	}

	/**
	 * 日志调试级别
	 * 
	 * @Title isDebugEnabled
	 * @return
	 * 
	 */
	public boolean isDebugEnabled() {
		return LogManager.getLogger(this.getClass()).isDebugEnabled();
	}

	/**
	 * 日志INFO级别
	 * 
	 * @Title isInfoEnabled
	 * @return
	 * 
	 */
	public boolean isInfoEnabled() {
		return LogManager.getLogger(this.getClass()).isInfoEnabled();
	}

	/**
	 * 日志追踪级别
	 * 
	 * @Title isTraceEnabled
	 * @return
	 * 
	 */
	public boolean isTraceEnabled() {
		return LogManager.getLogger(this.getClass()).isTraceEnabled();
	}

	private static String splitKey = ", ";

	/**
	 * 记录参数信息
	 * 
	 * @Title recordlogs
	 * @param logBean
	 *            {@link LogBean}
	 */
	private String recordLogs(LogBean logBean) {
		StringBuffer logsBuffer = new StringBuffer();
		logsBuffer.append("Method name is ").append(logBean.getMethodName()).append(" ");
		logsBuffer.append("Parameter is { ");
		LogBean.Parameter[] parameters = logBean.getParameter();
		for (int i = 0; i < parameters.length; i++) {
			if (i == parameters.length - 1) {
				logsBuffer.append(parameters[i]);
			} else {
				logsBuffer.append(parameters[i] + splitKey);
			}
		}
		logsBuffer.append(" } ");
		String[] message = logBean.getMessage();
		if (!ArrayUtils.isEmpty(message)) {
			logsBuffer.append("Additional Content {");
			for (int i = 0; i < message.length; i++) {
				if (i == message.length - 1) {
					logsBuffer.append(message[i]);
				} else {
					logsBuffer.append(message[i] + splitKey);
				}
			}

			logsBuffer.append(" }");
		}
		return logsBuffer.toString();
	}

	/**
	 * 记录参数信息
	 * 
	 * @param methodName
	 *            方法名
	 * @param args
	 *            方法参数
	 * @return 参数信息
	 * @throws NotFoundException
	 */
	// public String recordLogs(Class<?> clazz, String methodName, Object[]
	// args) throws NotFoundException {
	// StringBuffer logsBuff = new StringBuffer();
	// logsBuff.append("Class name is ").append(clazz.getName()).append(" ");
	// logsBuff.append("Method name is ").append(methodName).append(" ");
	// logsBuff.append("Parameter is [");
	// ClassPool.getDefault().insertClassPath(new
	// LoaderClassPath(clazz.getClassLoader()));
	// ClassPool pool = ClassPool.getDefault();
	// CtClass cc = pool.get(clazz.getName());
	// CtClass[] paras = new CtClass[args.length];
	// for (int i = 0; i < args.length; i++) {
	// if (null == args[i]) {
	// continue;
	// }
	// paras[i] = pool.get(args[i].getClass().getName());
	// }
	//
	// CtMethod cm = this.findCtMethodByCtClass(cc.getMethods(), paras,
	// methodName);
	// if (null == cm) {
	// return logsBuff.append("]").toString();
	// }
	//
	// // 使用javaassist的反射方法获取方法的参数名
	// MethodInfo methodInfo = cm.getMethodInfo();
	// CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
	// LocalVariableAttribute attr = (LocalVariableAttribute)
	// codeAttribute.getAttribute(LocalVariableAttribute.tag);
	// if (attr == null) {
	// // exception
	// return logsBuff.append("]").toString();
	// }
	// String[] paramNames = new String[cm.getParameterTypes().length];
	// int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
	// for (int i = 0; i < paramNames.length; i++)
	// paramNames[i] = attr.variableName(i + pos);
	// // paramNames即参数名
	// for (int i = 0; i < paramNames.length; i++) {
	// // logsBuff.append(cm.getParameterTypes()[i].getName());
	// if (null == args[i]) {
	// continue;
	// }
	// logsBuff.append(paramNames[i]);
	// logsBuff.append(" : ");
	// // 使用Json打印出所有参数
	// // logsBuff.append(args[i] instanceof Serializable ?
	// // JsonUtils.objToJson((Serializable) args[i]) : args[i]);
	//
	// logsBuff.append(args[i]);
	// if (i < paramNames.length - 1) {
	// logsBuff.append(splitKey);
	// }
	// }
	// logsBuff.append(']');
	// return logsBuff.toString();
	// }
	//
	// /**
	// * 获取当前执行的方法
	// *
	// * @param ctMethods
	// * {@link CtMethod} 类中所有可执行的方法
	// * @param paras
	// * {@link CtClass} 执行的方法参数
	// * @param methodName
	// * 执行方法名
	// * @return 当前执行的方法
	// */
	// private CtMethod findCtMethodByCtClass(CtMethod[] ctMethods, CtClass[]
	// paras, String methodName) {
	// for (CtMethod ctMethod : ctMethods) {
	// if (!ctMethod.getName().equals(methodName)) {
	// continue;
	// }
	// CtClass[] p = null;
	// try {
	// p = ctMethod.getParameterTypes();
	// } catch (NotFoundException e) {
	// continue;
	// }
	// if (p.length != paras.length) {
	// continue;
	// }
	// for (int i = 0; i < p.length; i++) {
	// if (!p[i].equals(paras[i])) {
	// continue;
	// }
	// }
	//
	// return ctMethod;
	// }
	//
	// return null;
	// }

}
